Feat/exclude completions of variable initializers#42087
Feat/exclude completions of variable initializers#42087sandersn merged 23 commits intomicrosoft:masterfrom
Conversation
… feat/exclude-completions-of-declared-variable
|
@andrewbranch Please look at this PR here.I am doing the same thing as you thought. I changed the existing test cases (because they had previously considered undeclared variables) and added a new test cases |
andrewbranch
left a comment
There was a problem hiding this comment.
Looks good, but I want to wait until more of the team is back after the holidays to add an additional review.
src/services/completions.ts
Outdated
| } | ||
|
|
||
| const variableDeclaration = findAncestor(property, (node) => { | ||
| if (isFunctionLikeDeclaration(node)) { |
There was a problem hiding this comment.
You may want to check if you’re actually in the body of the function, since this fails to filter out e.g. parameter defaults:
const fn = (p = /* 'fn' appears here */) => {}That said, leaving in some bad completions that we already have is not a big problem IMO, so this is a minor nitpick.
A similar comment applies to isVariableDeclaration(node): what you’re interested in is whether we walked up from the initializer of a variable declaration, but you might have a false positive on a case like this:
const { a, b = /**/ } = { ... }We’re not interested in getting the variable declaration if we started at the default binding for b. But, it ends up having no effect on the outcome, since there will be no symbol where symbol.valueDeclaration === variableDeclaration. But if it’s easy to skip that property access and equality check, we should do it, since it runs for every completion item. It could maybe shave off a couple milliseconds if the list is long.
This also brings up another point worth noting, that this logic won’t work for destructuring:
const { a, b } = { /** }; // 'a' and 'b' are offeredbut I don’t think it’s worth doing anything about this. I really don’t want to have to loop through every binding element declaration for every symbol—I’m happy that currently the check is only one equality comparison per symbol.
There was a problem hiding this comment.
-
You may want to check if you’re actually in the body of the function, since this fails to filter out e.g. parameter defaults:Yes. You are right, maybe we should use
isFunctionBlockto check. -
We’re not interested in getting the variable declaration if we started at the default binding for b. But, it ends up having no effect on the outcome, since there will be no symbol where symbol.valueDeclaration === variableDeclaration. But if it’s easy to skip that property access and equality check, we should do it, since it runs for every completion item. It could maybe shave off a couple milliseconds if the list is long.I think we can use the
isBindingPatternto filter out this two situations
const { a, b = /**/ } = { ... }
const [ a, b = /**/ ] = [ ... ]-
This also brings up another point worth noting, that this logic won’t work for destructuringI have the same idea with you. I think the time loss may be too much
For the 1 and 2, I have updated the code and added some test cases. Please help check it @andrewbranch
|
Supersedes #42056 |
src/services/completions.ts
Outdated
| function getVariableDeclaration(property: Node): VariableDeclaration | undefined { | ||
| const variableDeclaration = findAncestor(property, (node) => { | ||
| if (isFunctionLikeDeclaration(node)) { | ||
| if (isFunctionBlock(node) || isBindingPattern(node)) { |
There was a problem hiding this comment.
This doesn’t work for arrow function expressions without braces, e.g. () => expression/**/. It seems like there should be a util for this but I can’t find an existing one: isFunctionBlock(node) || isArrowFunction(node.parent) && node.parent.expression === node
There was a problem hiding this comment.
Yes. But I found no node.parent.expression. maybe node.parent.body?
isFunctionBlock(node) || (isArrowFunction(node.parent) && node.parent.body === node)
I has updated the code and add a new test case of arrow function expressions without braces
There was a problem hiding this comment.
Yeah, body is what I meant 👍
d9ab307 to
7b7cc24
Compare
| //// var x = this as/*1*/ | ||
|
|
||
| verify.completions({marker: "1", exact: completion.globalsPlus(["x"]) }) | ||
| verify.completions({marker: "1", exact: completion.globals }) |
There was a problem hiding this comment.
This was a very strange test
There was a problem hiding this comment.
This test has existed before, after this modification, there should be no 'x'. Let me optimize it
There was a problem hiding this comment.
I’m not saying there’s anything wrong here, just observing that it was weird for someone to write this test this way in the first place, a long time ago. I think the changes you made to these make sense 👍
b66e039 to
578a1ce
Compare
sandersn
left a comment
There was a problem hiding this comment.
Just some minor formatting requests -- the check and its tests look correct to me.
thanks for you suggestions. done @sandersn |
src/services/completions.ts
Outdated
| ? "quit" | ||
| : isVariableDeclaration(node)); | ||
|
|
||
| return variableDeclaration as VariableDeclaration; |
There was a problem hiding this comment.
shouldn't this be as VariableDeclaration | undefined?
There was a problem hiding this comment.
Yes. You are right. Done
Fixes #41731